'use client';

import React, { useEffect, useState } from 'react';
import PageTitle from '@/components/admin/common/PageTitle';
import Loading from '@/components/common/Loading';
import request from '@/utils/request';
import { DndContext, closestCenter, useSensor, useSensors, MouseSensor, TouchSensor, DragOverlay, } from '@dnd-kit/core';
import { SortableContext, useSortable, arrayMove, verticalListSortingStrategy, } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { GripVertical, Plus, Blocks, SquarePen, Trash2 } from 'lucide-react';
import { isEqual } from 'lodash';
import message from '@/components/common/message';
import Popup from '@/components/admin/common/Popup';
import PopupHeader from '@/components/admin/common/PopupHeader'
import SuperInput from '@/components/admin/common/SuperInput'
import SuperCheckbox from '@/components/admin/common/SuperCheckbox';
import ImageUpload from '@/components/admin/common/ImageUpload'
import IconButton from '@/components/common/IconButton';

function SortableMenuItem({ item, onDelete, onEdit, onAddChild, level = 0, addList = [] }) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: item.id });
  const style = { transform: CSS.Transform.toString(transform), transition, padding: '8px', margin: '4px', marginLeft: `${level * 20}px`, border: '1px solid #F1F1F1', backgroundColor: isDragging ? '#F1F1F1' : 'white', display: 'flex', justifyContent: 'space-between', alignItems: 'center', };
  return (
    <div ref={setNodeRef} style={style} className="group">
      <div className="flex items-center gap-2">
        <div {...listeners} {...attributes} className="cursor-grab text-gray-400"> <GripVertical size={16} /> </div>
        <span className='text-sm'>{item.name} ({item.url})</span>
      </div>
      <div className="flex gap-2">
        {!addList.includes(item.id) && <button className="btn btn-sm bg-blue-500 border-none rounded-xs" onClick={() => onAddChild(item.position, item.id)}><Blocks size={16} className='text-white' /></button>}
        <button className="btn btn-sm bg-green-500 border-none rounded-xs" onClick={() => onEdit(item)}><SquarePen size={16} className='text-white' /></button>
        <button className="btn btn-sm bg-red-500 border-none rounded-xs" onClick={() => onDelete(item.id)}><Trash2 size={16} className='text-white' /></button>
      </div>
    </div>
  );
}

function RenderMenuTree({ items, onDelete, onEdit, onAddChild, level = 0, addList = [] }) {
  return items.map(item => (
    <React.Fragment key={item.id}>
      <SortableMenuItem item={item} onDelete={onDelete} onEdit={onEdit} onAddChild={onAddChild} level={level} addList={addList} />
      {item.children && item.children.length > 0 && (
        <RenderMenuTree items={item.children} onDelete={onDelete} onEdit={onEdit} onAddChild={onAddChild} level={level + 1} addList={addList} />
      )}
    </React.Fragment>
  ));
}

function flattenTree(items, parentId = null, level = 0) {
  return items.reduce((acc, item) => {
    const newItem = { ...item, parentId, level };
    acc.push(newItem);
    if (item.children?.length) { acc.push(...flattenTree(item.children, item.id, level + 1)); }
    return acc;
  }, []);
}

function buildTree(items) {
  const map = new Map();
  const roots = [];
  items.forEach(item => {
    map.set(item.id, { ...item, children: [] });
  });
  items.forEach(item => {
    if (item.parentId && map.has(item.parentId)) {
      map.get(item.parentId).children.push(map.get(item.id));
    } else {
      roots.push(map.get(item.id));
    }
  });
  return roots;
}

function reassignSortOrder(items) {
  return items.map((item, index) => {
    const newItem = { ...item, sort: index + 1, };
    if (item.children && item.children.length > 0) {
      newItem.children = reassignSortOrder(item.children);
    }
    return newItem;
  });
}

export default function NavigationPage() {
  const [loaded, setLoaded] = useState(false);
  const [originNavigations, setOriginNavigations] = useState({});
  const [navigations, setNavigations] = useState({});
  const [isEding, setIsEditing] = useState(false);
  const [activeId, setActiveId] = useState(null);
  const [draggedItem, setDraggedItem] = useState(null);
  const [addList, setAddList] = useState([]);
  const [isPopupOpen, setIsPopupOpen] = useState(false);
  const [currentValue, setCurrentValue] = useState({});
  const [isAddStatus, setIsAddStatus] = useState(false);
  const [addPosition, setAddPosition] = useState('');

  const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor));

  useEffect(() => {
    fetchNavigations();
  }, []);

  const fetchNavigations = async () => {
    const res = await request('/api/navigations');
    if (res.code === 0) {
      setNavigations(res.data);
      setOriginNavigations(res.data);
    }
    setLoaded(true);
  };

  const handleDragEnd = (position) => (event) => {
    const { active, over } = event;
    setActiveId(null);
    setDraggedItem(null);
    if (!over || active.id === over.id) return;

    const flatItems = flattenTree(navigations[position]);
    const oldIndex = flatItems.findIndex(i => i.id === active.id);
    const newIndex = flatItems.findIndex(i => i.id === over.id);
    const moved = arrayMove(flatItems, oldIndex, newIndex);
    const sorted = reassignSortOrder(moved);
    const tree = buildTree(sorted);
    setNavigations(prev => ({ ...prev, [position]: tree }));
  };

  useEffect(() => {
    const isEding = !isEqual(navigations, originNavigations);
    setIsEditing(isEding);
  }, [navigations, originNavigations]);

  const handleDelete = (id) => {
    const newNavigations = {};
    for (const position in navigations) {
      const removeItem = (items) => items.filter(i => i.id !== id).map(i => ({ ...i, children: i.children ? removeItem(i.children) : [] }));
      newNavigations[position] = removeItem(navigations[position]);
    }
    if (addList.includes(id)) { setAddList(prev => prev.filter(i => i !== id)); }
    setNavigations(newNavigations);
  };

  const handleEdit = (item) => {
    setIsAddStatus(false);
    openPopup(item);
  };

  const handleAdd = (position) => {
    setAddPosition(position);
    setIsAddStatus(true);
    openPopup({ id: Date.now(), name: '', status: 0, description: '', url: '', icon: '', position, parent_id: null, children: [] });
  };

  const handleAddChild = (position, parentId) => {
    setAddPosition(position);
    setIsAddStatus(true);
    openPopup({ id: Date.now(), name: '', status: 0, description: '', url: '', icon: '', position, parent_id: parentId, children: [] });
  };

  const handleSave = async () => {
    const res = await request('/api/admin/navigations', { method: 'POST', body: JSON.stringify(navigations) });
    if (res.code === 0) {
      fetchNavigations();
      setIsEditing(false);
      setAddList([]);
      message.success('保存成功');
    } else {
      message.error(res.codeMap[res.code]);
    }
  }

  const handleReset = () => {
    setNavigations(originNavigations);
    setIsEditing(false);
  }

  const openPopup = (item) => {
    setCurrentValue(item);
    setIsPopupOpen(true);
  }

  const closePopup = () => {
    setAddPosition('');
    setIsAddStatus(false);
    setCurrentValue({});
    setIsPopupOpen(false);
  }

  const changeItem = async () => {
    if (currentValue.name === '' || currentValue.position === '' || currentValue.url === '') return message.error('名称、位置、URL都不能为空');
    if (isAddStatus) {
      if (currentValue.parent_id) {
        const newNavigations = {};
        for (const position in navigations) {
          const addChild = (items) =>
            items.map(i => {
              if (i.id === currentValue.parent_id) { return { ...i, children: [...(i.children || []), currentValue], }; }
              if (i.children) { return { ...i, children: addChild(i.children) }; }
              return i;
            });
          newNavigations[position] = addChild(navigations[position]);
        }
        setNavigations(newNavigations);
      } else {
        const id = Date.now();
        setAddList(prev => [...prev, id]);
        setNavigations(prev => ({ ...prev, [addPosition]: reassignSortOrder([...(prev[addPosition] || []), currentValue]), }));
      }

    } else {
      const newNavigations = {};
      for (const position in navigations) {
        const editItem = (items) =>
          items.map(i => {
            if (i.id === currentValue.id) return { ...i, ...currentValue };
            if (i.children) return { ...i, children: editItem(i.children) };
            return i;
          });
        newNavigations[position] = editItem(navigations[position]);
      }
      setNavigations(newNavigations);
    }
    closePopup();
  }

  const handleChange = (key, value) => {
    setCurrentValue(prev => ({ ...prev, [key]: value }));
  }

  const content = (
    <div>
      <Popup isOpen={isPopupOpen} onClose={closePopup}>
        <PopupHeader title={'编辑导航信息'} buttonText={'保存'} onButtonClick={changeItem} />
        <form onSubmit={e => e.preventDefault()}>
          <SuperInput label={'名称'} autoComplete={'name'} state={true} value={currentValue?.name} handleChange={(value) => handleChange('name', value)} />
          <SuperInput label={'链接'} autoComplete={'url'} state={true} value={currentValue?.url} handleChange={(value) => handleChange('url', value)} />
          <ImageUpload label={'Icon'} state={true} value={currentValue?.icon} handleChange={(value) => handleChange('icon', value)}/>
          <SuperInput label={'描述'} autoComplete={'description'} state={true} value={currentValue?.description} handleChange={(value) => handleChange('description', value)} />
          <SuperInput label={'位置'} autoComplete={'position'} state={false} value={currentValue?.position} handleChange={(value) => handleChange('position', value)} />
          <SuperCheckbox label={'状态'} checked={currentValue?.status === 0 ? true : false} currentValue={currentValue?.status === 0 ? "已启用" : "已禁用"} state={true} onChange={(value) => handleChange('status', value === true ? 0 : 1)} />
        </form>
      </Popup>
      <PageTitle title="导航管理" buttonText={isEding ? '保存' : ''} onButtonClick={handleSave} extraButtonText={isEding ? '重置' : ''} onExtraButtonClick={handleReset} />
      <div className='max-w-[100%] mx-auto '>
        <div className='flex flex-col mt-2'>
          {Object.entries(navigations).map(([position, items]) => (
            <div key={position} className='flex flex-col bg-white rounded-sm p-4 mb-2'>
              <div className="x-header flex justify-between items-center mb-2"> <h3 className='capitalize font-medium text-xs'>{position}</h3> </div>
              <div className='x-content'>
                <DndContext
                  sensors={sensors}
                  collisionDetection={closestCenter}
                  onDragStart={e => {
                    setActiveId(e.active.id);
                    const flat = flattenTree(items);
                    const dragging = flat.find(i => i.id === e.active.id);
                    setDraggedItem(dragging);
                  }}
                  onDragEnd={handleDragEnd(position)}
                >
                  <SortableContext items={flattenTree(items).map(i => i.id)} strategy={verticalListSortingStrategy} >
                    <RenderMenuTree items={items} onDelete={handleDelete} onEdit={handleEdit} onAddChild={handleAddChild} addList={addList} />
                  </SortableContext>
                  <DragOverlay>
                    {draggedItem && (
                      <div className="p-2 bg-base-200 border border-gray-300 rounded-xs">
                        {draggedItem.name}
                      </div>
                    )}
                  </DragOverlay>
                </DndContext>
              </div>
              <div className='x-add-btn mt-4 flex justify-center'><IconButton onClick={() => handleAdd(position)}><Plus color="#FFFFFF"/></IconButton></div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );

  return <div>{loaded ? content : <Loading />}</div>;
}
